package com.sdy.resdir.web.controller;

import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.sdy.auth.api.model.UserInfo;
import com.sdy.auth.client.service.SsoService;
import com.sdy.common.model.BizException;
import com.sdy.common.utils.Assert;
import com.sdy.resdir.biz.model.*;
import com.sdy.resdir.biz.service.*;
import com.sdy.common.utils.StringUtil;
import com.sdy.common.model.Response;
import com.sdy.resdir.biz.vo.ResItemExcelVo;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.*;
import com.sdy.mvc.controller.BaseController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import com.sdy.mvc.service.FileService;
import org.testng.annotations.IFactoryAnnotation;

import static org.apache.poi.ss.usermodel.CellType.NUMERIC;
import static org.apache.poi.ss.usermodel.CellType.STRING;

/**
 * 资源目录-数据源 前端控制器
 *
 * @author cgj
 * @since 2019-11-22
 */
@Slf4j
@RestController
@SuppressWarnings("unchecked")
@RequestMapping("/rdResourceDirData")
@Api(tags = "资源编目")
public class RdResourceDirDataController extends BaseController {
    @Autowired
    private RdResourceDirDataService rdResourceDirDataService;
    @Autowired
    private RdResDataItemService dataItemService;
    @Autowired
    private SsoService ssoService;
    @Autowired
    private RdDirDataUpdateLogService updateLogService;
    @Autowired
    private RdResourceDirService rdResourceDirService;
    @Autowired
    private RdResDataItemService rdResDataItemService;
    @Autowired
    private RdResDetailsApiService rdResDetailsApiService;
    @Autowired
    private RdParameterInformationService rdParameterInformationService;

    @ApiOperation(value = "资源编目根据所属资源ID查询详情", response = RdResourceDirData.class)
    @ApiImplicitParam(name = "id", value = "resId", type = "Integer")
    @GetMapping("/getResInfoByResId")
    public Response getResLogByResId(Integer id, HttpServletRequest request) throws BizException {
        Assert.isNull(id, "id不可为空");
        RdResourceDir oneDir = rdResourceDirService.getById(id);
        Map<String, Object> resdirInfos = new HashMap<>(16);
        if (oneDir != null && (oneDir.getResType() == 3 )) {
            RdResourceDirData dirData = rdResourceDirDataService.getOne(Wrappers.<RdResourceDirData>lambdaQuery().eq(RdResourceDirData::getResDirId, id));
            // RdResourceDirData dirData = new RdResourceDirData();
            if (dirData!=null) {
                List<RdResDataItem> items = rdResDataItemService.list(Wrappers.<RdResDataItem>lambdaQuery().eq(RdResDataItem::getOwnResId, id));
                dirData.setDataItems(items);
                List<RdDirDataUpdateLog> list = updateLogService.list(Wrappers.<RdDirDataUpdateLog>lambdaQuery().eq(RdDirDataUpdateLog::getResCatalogId, dirData.getId()));
                dirData.setUpdateLogs(list);
                resdirInfos.put("exchangeData", dirData);
            }
        } else if (oneDir != null && oneDir.getResType() == 1) {
            RdResDetailsApi rdResDetailApi = rdResDetailsApiService.getOne(new LambdaQueryWrapper<RdResDetailsApi>().eq(RdResDetailsApi::getResDirId, id));
            if (rdResDetailApi!=null) {
            // 获取请求参数
            List<RdParameterInformation> requestParamList = rdParameterInformationService.list(new LambdaQueryWrapper<RdParameterInformation>()
                    .eq(RdParameterInformation::getOwnResId, rdResDetailApi.getId())
                    .eq(RdParameterInformation::getParameterType, 0));
            // 获取返回参数
            List<RdParameterInformation> returnParamList = rdParameterInformationService.list(new LambdaQueryWrapper<RdParameterInformation>()
                    .eq(RdParameterInformation::getOwnResId, rdResDetailApi.getId())
                    .eq(RdParameterInformation::getParameterType, 1));

                rdResDetailApi.setRequestParamInfo(requestParamList);
                rdResDetailApi.setReturnParamInfo(returnParamList);
                resdirInfos.put("apiData", rdResDetailApi);
            }
        }else if (oneDir!=null&&oneDir.getResType() == 2){
            RdResourceDirData dirData = rdResourceDirDataService.getOne(Wrappers.<RdResourceDirData>lambdaQuery().eq(RdResourceDirData::getResDirId, id));
            resdirInfos.put("dirData",dirData);

        }
        return Response.success(resdirInfos);
    }

    @ApiOperation(value = "新增或者修改编目信息")
    @PostMapping("/updateOrSaveDirData")
    public Response updateOrSaveDirData(@RequestBody @ApiParam(name = "dirData") RdResourceDirData data, HttpServletRequest request) throws BizException {
        UserInfo userInfo = ssoService.getUserInfo(request);
        Assert.isNull(userInfo, "未登录");
        rdResourceDirDataService.updateOrSaveDirData(data, userInfo);
        return Response.success();
    }

    @ApiOperation(value = "下载Excel模板文件")
    @GetMapping("/downLoadTemplateExcelFile")
    public void downLoadTemplateExcelFile(HttpServletResponse response) throws IOException {
        Resource resources = new ClassPathResource("file/资源编目-数据导入模板文件.xls");
        InputStream inputStreams = resources.getInputStream();
        String filenames = resources.getFilename();
        response.setContentType("application/force-download");
        OutputStream outputStreams = response.getOutputStream();
        response.setHeader("Content-Disposition", "attachment;fileName=" + new String(filenames.getBytes("UTF-8"), "ISO-8859-1"));
        int b = 0;
        byte[] buffer = new byte[1000000];
        while (b != -1) {
            b = inputStreams.read(buffer);
            if (b != -1) {
                outputStreams.write(buffer, 0, b);
            }
        }
        inputStreams.close();
        outputStreams.close();
        outputStreams.flush();
    }

    @ApiOperation(value = "首页下载资源列表")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "resName", value = "模糊查询资源名称"),
            @ApiImplicitParam(name = "isOnline", value = "资源是否上线:1-已上线 2-未上线"),
            @ApiImplicitParam(name = "resType", value = "资源类型:1.服务接口类 2.服务页面类 3.数据教换类"),
            @ApiImplicitParam(name = "resLevel", value = "资源层级:1.省级 2.市级 3.区级"),
            @ApiImplicitParam(name = "resPower", value = "资源状态:1.公开 2.受限"),
            @ApiImplicitParam(name = "resPowerDept", value = "资源权限部门")}
    )
    @GetMapping("/downLoadResItem")
    public void downLoadResItem(HttpServletResponse response, Integer isOnline, Integer resType, Integer resLevel, Integer resPower, Integer resPowerDept) throws IOException {
        List<RdResourceDir> rdResourceDirList = rdResourceDirService.list(Wrappers.<RdResourceDir>lambdaQuery()
                .eq(null != isOnline, RdResourceDir::getCollectionSituation, isOnline)
                .eq(null != resType, RdResourceDir::getResType, resType)
                .eq(null != resLevel, RdResourceDir::getResLevel, resLevel)
                .eq(null != resPower, RdResourceDir::getResPower, resPower)
                .eq(null != resPowerDept, RdResourceDir::getResPowerDeptId, resPowerDept)
                .eq(RdResourceDir::getIsRelease, 1));
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("资源列表下载", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");
        ServletOutputStream output = response.getOutputStream();
        ExcelWriter writer = new ExcelWriter(output, ExcelTypeEnum.XLS, true);
        Sheet sheet = new Sheet(1, 0, ResItemExcelVo.class);
        sheet.setSheetName("第一页");
        List<ResItemExcelVo> voList = setResItemData(rdResourceDirList);
        writer.write(voList, sheet);
        writer.finish();
        output.flush();
    }

    private List<ResItemExcelVo> setResItemData(List<RdResourceDir> rdResourceDirList) {
        List<ResItemExcelVo> voList = new ArrayList<>();
        int i = 1;
        for (RdResourceDir dir : rdResourceDirList) {
            ResItemExcelVo resItemExcelVo = new ResItemExcelVo().setResNo(i++).setResName(dir.getResName()).setResSourceDept(dir.getResSourceDept());
            // 资源类型:1.服务接口类 2.服务页面类 3.数据教换类
            resItemExcelVo.setResType(dir.getResType() != null && dir.getResType() == 1 ? "服务接口类" : dir.getResType() != null && dir.getResType() == 2 ? "服务页面类" : "数据交换类");
            // 资源状态:1.公开 2.受限
            resItemExcelVo.setResPower(dir.getResPower() != null && dir.getResPower() == 1 ? "公开" : "受限");
            // 资源层级:1.省级 2.市级 3.区级
            resItemExcelVo.setResLevel(dir.getResLevel() != null && dir.getResLevel() == 1 ? "省级" : dir.getResLevel() != null && dir.getResLevel() == 2 ? "市级" : "区级");
            // 资源是否上线:1-已上线 2-未上线
            resItemExcelVo.setCollectionSituation(dir.getCollectionSituation() != null && dir.getCollectionSituation() == 1 ? "已归集" : "未归集");
            voList.add(resItemExcelVo);
        }
        return voList;
    }

    @ApiOperation(value = "上传Excel文件将数据以列表形式返回")
    @PostMapping("/readExcelToList")
    public Response readExcelToList(@RequestPart("file") MultipartFile file) throws IOException, BizException {
        String filename = file.getOriginalFilename();
        Assert.isNull(filename, "无法获取文件信息");
        Assert.isTrue(!filename.contains(".xls"), "上传文件类型错误");
        // 获取文件输入流
        InputStream inputStream = file.getInputStream();
        // 获取excel工作簿对象
        List<RdResDataItem> tableInfos = new ArrayList<>();
        String substring = filename.substring(filename.lastIndexOf("."), filename.length());
        if (".xls".equals(substring)) {
            HSSFWorkbook workbook = new HSSFWorkbook(file.getInputStream());
            tableInfos = excelToList(workbook);
        } else if (".xlsx".equals(substring)) {
            XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
            tableInfos = excelxToList(workbook);
        }
        // 关闭输入流
        inputStream.close();
        return Response.success(tableInfos);
    }

    /**
     * 文件是.xls
     *
     * @param workbook
     * @return
     */
    private List<RdResDataItem> excelToList(HSSFWorkbook workbook) throws BizException {
        // 得到excel工作表对象
        HSSFSheet sheetAt = workbook.getSheetAt(0);
        List<RdResDataItem> list = Lists.newArrayList();
        for (int i = 0; i < sheetAt.getLastRowNum() + 1; i++) {
            Row row = sheetAt.getRow(i);
            //首行（即表头）不读取
            if (row != null) {
                if (row.getRowNum() == 0 || row.getRowNum() == 1 || row.getRowNum() == 2) {
                    continue;
                }
                //读取当前行中单元格数据，索引从0开始
                String colName = null;
                if (row.getCell(0) != null) {
                    row.getCell(0).setCellType(STRING);
                    colName = row.getCell(0).getStringCellValue();
                }
                String colDesc = null;
                if (row.getCell(1) != null) {
                    row.getCell(1).setCellType(STRING);
                    colDesc = row.getCell(1).getStringCellValue();
                }
                String colType = null;
                String substring = null;
                if (row.getCell(2) != null) {
                    row.getCell(2).setCellType(STRING);
                    colType = row.getCell(2).getStringCellValue();
                    substring = colType.contains("(") ? colType.substring(0, colType.lastIndexOf("(")) : colType;
                }
                double colLength = 0;
                if (row.getCell(3) != null && "number".equals(substring)) {
                    row.getCell(3).setCellType(NUMERIC);
                    colLength = row.getCell(3).getNumericCellValue();
                }
                double colPrecesion = 0;
                if (row.getCell(4) != null && "number".equals(substring)) {
                    row.getCell(4).setCellType(NUMERIC);
                    colPrecesion = row.getCell(4).getNumericCellValue();
                }
                String ifKey = null;
                if (row.getCell(5) != null) {
                    row.getCell(5).setCellType(STRING);
                    ifKey = row.getCell(5).getStringCellValue();
                }
                RdResDataItem item = new RdResDataItem();
                item.setChineseName(colDesc);
                item.setEnglishName(colName);
                item.setFieldType(substring);
                item.setFieldLength(colLength + "");
                item.setFieldAccuracy(colPrecesion + "");
                if (null != ifKey && "YES".equals(ifKey)) {
                    item.setKeywords(1);
                } else {
                    item.setKeywords(2);
                }
                if (StringUtil.isNotBlank(colName) && StringUtil.isNotBlank(colDesc) && StringUtil.isNotBlank(colType)) {
                    list.add(item);
                }
            }
        }
        return list;
    }

    /**
     * 文件是.xlsx
     *
     * @param workbook
     * @return
     */
    private List<RdResDataItem> excelxToList(XSSFWorkbook workbook) throws BizException {
        // 得到excel工作表对象
        XSSFSheet sheetAt = workbook.getSheetAt(0);
        List<RdResDataItem> list = Lists.newArrayList();
        for (int i = 0; i < sheetAt.getLastRowNum(); i++) {
            Row row = sheetAt.getRow(i);
            if (row != null) {
                //首行（即表头）不读取
                if (row.getRowNum() == 0 || row.getRowNum() == 1 || row.getRowNum() == 2) {
                    continue;
                }
                //读取当前行中单元格数据，索引从0开始
                String colName = null;
                if (row.getCell(0) != null) {
                    colName = row.getCell(0).getStringCellValue();
                }
                String colDesc = null;
                if (row.getCell(1) != null) {
                    colDesc = row.getCell(1).getStringCellValue();
                }
                Assert.isNull(row.getCell(2), "字段类型不能为空");
                String colType = null;
                String substring = null;
                if (row.getCell(2) != null) {
                    colType = row.getCell(2).getStringCellValue();
                    substring = colType.contains("(") ? colType.substring(0, colType.lastIndexOf("(")) : colType;
                }
                Double colLength = 0.0;
                if (row.getCell(3) != null) {
                    colLength = row.getCell(3).getNumericCellValue();
                }
                Double colPrecesion = 0.0;
                if (row.getCell(4) != null) {
                    colPrecesion = row.getCell(4).getNumericCellValue();
                }
                String ifKey = null;
                if (row.getCell(5) != null) {
                    ifKey = row.getCell(5).getStringCellValue();
                }
                RdResDataItem item = new RdResDataItem();
                item.setChineseName(colDesc);
                item.setEnglishName(colName);
                item.setFieldType(substring);
                item.setFieldLength(colLength + "");
                item.setFieldAccuracy(colPrecesion + "");
                if (null != ifKey && "YES".equals(ifKey)) {
                    item.setKeywords(1);
                } else {
                    item.setKeywords(2);
                }
                if (StringUtil.isNotBlank(colName) && StringUtil.isNotBlank(colDesc) && StringUtil.isNotBlank(colType)) {
                    list.add(item);
                }
            }
        }
        return list;
    }

//    /**
//     * 循环存数据
//     *
//     * @param list
//     * @param row
//     */
//    private void forSheetAt(List<RdResDataItem> list, Row row) throws BizException {
//        if (row.getRowNum() == 0 || row.getRowNum() == 1 || row.getRowNum() == 2) {
//            return;
//        }
//        //读取当前行中单元格数据，索引从0开始
//        Assert.isNull(row.getCell(0), "字段名不能为空");
//        String colName = row.getCell(0).getStringCellValue();
//        String colDesc = null;
//        if (row.getCell(1) != null) {
//            colDesc = row.getCell(1).getStringCellValue();
//        }
//        Assert.isNull(row.getCell(2), "字段类型不能为空");
//        String colType = row.getCell(2).getStringCellValue();
//        String substring = colType.contains("(") ? colType.substring(0, colType.lastIndexOf("(")) : colType;
//        Double colLength = null;
//        if (row.getCell(3) != null) {
//            colLength = row.getCell(3).getNumericCellValue();
//        }
//        Double colPrecesion = null;
//        if (row.getCell(4) != null) {
//            colPrecesion = row.getCell(4).getNumericCellValue();
//        }
//        String ifKey = null;
//        if (row.getCell(5) != null) {
//            ifKey = row.getCell(5).getStringCellValue();
//        }
//        if ("".equals(colName) && "".equals(colType) && colLength == null && colPrecesion == null && "".equals(ifKey)) {
//
//        }
//        RdResDataItem item = new RdResDataItem();
//        item.setChineseName(colDesc);
//        item.setEnglishName(colName);
//        item.setFieldType(substring);
//        item.setFieldLength(colLength + "");
//        item.setFieldAccuracy(colPrecesion + "");
//        if (null != ifKey && "YES".equals(ifKey)) {
//            item.setKeywords(1);
//        } else {
//            item.setKeywords(2);
//        }
//        list.add(item);
//    }
}
